﻿using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System;
using System.Threading.Tasks;

namespace Akka.Ext.Http.Mvc
{
    class AkkaHttpMvcMiddleware
    {
        private readonly RequestDelegate next;
        private readonly string path;
        AkkaHttpClient client;
        Func<RequestInfo, HttpRequest, string> onBefore;
        Action<ResponseInfo, HttpResponse> onAfter;

        public AkkaHttpMvcMiddleware(RequestDelegate next, string path, AkkaHttpClient client, Func<RequestInfo, HttpRequest, string> onBefore, Action<ResponseInfo, HttpResponse> onAfter = null)
        {
            this.next = next;
            this.path = path;
            this.client = client;
            this.onBefore = onBefore;
            this.onAfter = onAfter;
        }

        public async Task Invoke(HttpContext httpcontext)
        {
            if (!httpcontext.Request.Path.StartsWithSegments(path))
            {
                await next(httpcontext);
            }
            else
            {
                try
                {
                    var req = new RequestInfo();
                    string actorPath = onBefore(req, httpcontext.Request);
                    if (!string.IsNullOrEmpty(actorPath))
                    {
                        await CommonUtils.CreateRequestInfo(httpcontext.Request, req);
                        var res = await client.ExecuteAsync(actorPath, req);
                        await CommonUtils.CreateResponseInfo(httpcontext.Response, res);
                        onAfter?.Invoke(res, httpcontext.Response);
                    }
                    else
                    {
                        var res = new ResponseInfo { Code = -1, IsSuccess = false, ErrorMessage = "actorPath is null or empty" };
                        onAfter?.Invoke(res, httpcontext.Response);
                    }
                }
                catch (Exception ex)
                {
                    var res = new ResponseInfo { Code = -1, IsSuccess = false, ErrorMessage = ex.Message };
                    onAfter?.Invoke(res, httpcontext.Response);
                }
            }
        }
    }

    public static class AkkaHttpMvcMiddlewareExtensions
    {
        public static IApplicationBuilder UseAkkaHttp(this IApplicationBuilder builder, string path, AkkaHttpClient client, Func<RequestInfo, HttpRequest, string> onBefore, Action<ResponseInfo, HttpResponse> onAfter = null)
        {
            return builder.UseMiddleware<AkkaHttpMvcMiddleware>(path, client, onBefore, onAfter);
        }
    }
}
